package com.chendx.store.behavior.service.impl;

import com.chendx.model.behivor.dto.UserBehaviorDto;
import com.chendx.model.behivor.pojo.UserCollect;
import com.chendx.model.behivor.pojo.UserFocus;
import com.chendx.model.common.dtos.PageRequestDto;
import com.chendx.model.common.dtos.PageResponseResult;
import com.chendx.model.common.dtos.ResponseResult;
import com.chendx.model.common.enums.AppHttpCodeEnum;
import com.chendx.model.goods.pojo.Sku;
import com.chendx.model.goods.pojo.Spu;
import com.chendx.model.user.pojo.User;
import com.chendx.store.behavior.feign.GoodsFeign;
import com.chendx.store.behavior.service.UserBehaviorService;
import com.chendx.store.utils.AppThreadLocalUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by chendx on 2022/4/20.
 */
@Service
public class UserBehaviorServiceImpl implements UserBehaviorService {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private GoodsFeign goodsFeign;

    @Override
    public ResponseResult focus(UserBehaviorDto dto) {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer userId = user.getId();
        String userName = user.getUsername();
        if (dto == null || StringUtils.isEmpty(dto.getSkuId())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        Query query = Query.query(Criteria.where("skuId").is(dto.getSkuId()).and("userId").is(userId));
        UserFocus userFocus = mongoTemplate.findOne(query, UserFocus.class, "user_focus");

        //创建rabbit管理器
        RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate.getConnectionFactory());
        //新建交换机
        DirectExchange exchange = new DirectExchange("sku_focus");
        //声明交换机
        rabbitAdmin.declareExchange(exchange);
        //创建队列
        Queue queue = new Queue("sku_focus_" + userName);
        //创建绑定
        Binding binding = BindingBuilder.bind(queue).to(exchange).with(dto.getSkuId());
        rabbitAdmin.declareBinding(binding);
        if (userFocus == null) {
            userFocus = new UserFocus();
            userFocus.setUserId(userId);
            userFocus.setUserName(userName);
            userFocus.setSkuId(dto.getSkuId());
            userFocus.setCategoryId(dto.getCategoryId());
            userFocus.setCategoryName(dto.getCategoryName());
            mongoTemplate.save(userFocus);
            //声明 绑定队列
            rabbitAdmin.declareQueue(queue);
            rabbitAdmin.declareBinding(binding);
        } else {
            mongoTemplate.remove(query, UserFocus.class,  "user_focus");
            rabbitAdmin.removeBinding(binding);
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult isFocus(String skuId) {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer userId = user.getId();
        String userName = user.getUsername();
        if (StringUtils.isEmpty(skuId)){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        Query query = Query.query(Criteria.where("skuId").is(skuId).and("userId").is(userId));
        UserFocus userFocus = mongoTemplate.findOne(query, UserFocus.class, "user_focus");
        if (userFocus != null){
            return ResponseResult.errorResult(AppHttpCodeEnum.IS_FOCUS);
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.NO_FOCUS);
    }

    @Override
    public ResponseResult collect(UserBehaviorDto dto) {
        if (dto == null || StringUtils.isEmpty(dto.getSpuId())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer userId = user.getId();
        String userName = user.getUsername();
        Query query = Query.query(Criteria.where("spuId").is(dto.getSpuId()).and("userId").is(userId));
        UserCollect userCollect = mongoTemplate.findOne(query, UserCollect.class, "user_collect");
        if (userCollect == null) {
            userCollect = new UserCollect();
            userCollect.setUserId(userId);
            userCollect.setUserName(userName);
            userCollect.setSpuId(dto.getSpuId());
            userCollect.setCategoryId(dto.getCategoryId());
            userCollect.setCategoryName(dto.getCategoryName());
            mongoTemplate.save(userCollect);
        } else {
            mongoTemplate.remove(query, UserFocus.class,  "user_collect");
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult isCollect(String spuId) {
        if (StringUtils.isEmpty(spuId)){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer userId = user.getId();
        String userName = user.getUsername();
        Query query = Query.query(Criteria.where("spuId").is(spuId).and("userId").is(userId));
        UserCollect userCollect = mongoTemplate.findOne(query, UserCollect.class, "user_collect");
        if (userCollect != null){
            return ResponseResult.errorResult(AppHttpCodeEnum.IS_COLLECT);
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.NO_COLLECT);
    }

    @Override
    public ResponseResult focusCount() {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer userId = user.getId();
        String userName = user.getUsername();
        Query query = Query.query(Criteria.where("userId").is(userId));
        long count = 0;
        try {
            count = mongoTemplate.count(query, UserFocus.class);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.okResult(count);
        }
        return ResponseResult.okResult(count);
    }

    @Override
    public ResponseResult collectCount() {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer userId = user.getId();
        String userName = user.getUsername();
        Query query = Query.query(Criteria.where("userId").is(userId));
        long count = 0;
        try {
            count = mongoTemplate.count(query, UserCollect.class);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.okResult(count);
        }
        return ResponseResult.okResult(count);
    }

    @Override
    public List<UserFocus> focus4user(String id) {
        List<UserFocus> userFocuses = new ArrayList<>();
        if (StringUtils.isEmpty(id)){
            return userFocuses;
        }
        Query query = Query.query(Criteria.where("skuId").is(id));
        userFocuses = mongoTemplate.find(query, UserFocus.class);
        return userFocuses;
    }

    @Override
    public ResponseResult loadCollection() {
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer userId = user.getId();
        String userName = user.getUsername();

        Query query = Query.query(Criteria.where("userId").is(userId).and("userName").is(userName));
        List<UserCollect> userCollects = mongoTemplate.find(query, UserCollect.class);
        List<String> spuIds = userCollects.stream().map(x -> x.getSpuId()).collect(Collectors.toList());
        List<Spu> spuList = new ArrayList<>();
        for (String spuId : spuIds){
            Spu spu = goodsFeign.findById(Long.valueOf(spuId));
            spuList.add(spu);
        }
        return ResponseResult.okResult(spuList);
    }

    @Override
    public ResponseResult loadFocus(PageRequestDto dto) {
        dto.checkParam();
        dto.setSize(6);
        User user = AppThreadLocalUtils.get();
        if (user == null || user.getId() == null || user.getUsername() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        Integer userId = user.getId();
        String userName = user.getUsername();

        Query query = Query.query(Criteria.where("userId").is(userId).and("userName").is(userName));
        query.limit(dto.getPage() * dto.getSize());
        List<UserFocus> userCollects = mongoTemplate.find(query, UserFocus.class);

        List<String> skuIds = userCollects.stream().map(x -> x.getSkuId()).collect(Collectors.toList());
        List<Sku> skuList = new ArrayList<>();
        for (String skuId : skuIds){
            Sku sku = goodsFeign.findSkuById(Long.valueOf(skuId));
            skuList.add(sku);
        }
        PageResponseResult pageResponseResult = new PageResponseResult(dto.getPage(),dto.getSize(),skuList.size());
        pageResponseResult.setData(skuList);
        return pageResponseResult;
    }
}
